package com.avcdata.security;

import com.avcdata.base.JSONResult;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.io.IOException;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;

public class TokenAuthenticationService {

  static final long EXPIRATIONTIME = 432_000_000;     // 5天
  static final String SECRET = "P@ssw02d";            // JWT密码
  static final String TOKEN_PREFIX = "Bearer";        // Token前缀
  static final String HEADER_STRING = "Authorization";// 存放Token的Header Key

  public static void addAuthentication(HttpServletResponse response,
      Authentication authentication) {

    // 这是从CustomAuthenticationProvider成功后传入的 grantedAuthorities为用户名和角色不同传入不同的权限
    Collection<GrantedAuthorityImpl> grantedAuthorities = (Collection<GrantedAuthorityImpl>) authentication
        .getAuthorities();

    // 生成一个权限字符串 准备签入token中
    StringBuilder authorities = new StringBuilder();
    grantedAuthorities.forEach(a -> {
      System.out.println(a.getAuthority());
      authorities.append(a.getAuthority());
    });

    // 生成JWT
    String JWT = Jwts.builder()
        // 保存权限（角色）
        .claim("authorities", authorities)
        // 用户名写入标题
        .setSubject(authentication.getName())
        // 有效期设置
        .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
        // 签名设置
        .signWith(SignatureAlgorithm.HS512, SECRET)
        .compact();

    // 将 JWT 写入 body
    try {
      response.setContentType("application/json");
      response.setStatus(HttpServletResponse.SC_OK);
      response.getOutputStream().println(JSONResult.fillResultString(0, "", JWT));
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  public static Authentication getAuthentication(HttpServletRequest request) {
    // 从Header中拿到token
    String token = request.getHeader(HEADER_STRING);

    if (token != null) {
      // 解析 Token
      Claims claims = Jwts.parser()
          // 验签
          .setSigningKey(SECRET)
          // 去掉 Bearer
          .parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
          .getBody();

      // 拿用户名
      String user = claims.getSubject();

      // 得到 权限（角色）
      List<GrantedAuthority> authorities = AuthorityUtils
          .commaSeparatedStringToAuthorityList((String) claims.get("authorities"));

      // 返回验证令牌 会将权限authorities交给security去判断是否可访问接口 在WebSecurityConfig中已配置
      return user != null ?
          new UsernamePasswordAuthenticationToken(user, null, authorities) :
          null;
    }
    return null;
  }
}
